package com.wz.jiangsu.service.es.serviceImpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.wz.jiangsu.bean.entity.wazuh.WazuhSecurityEventDataCommonDtoToES;
import com.wz.jiangsu.bean.vo.es.QueryESCondition;
import com.wz.jiangsu.bean.vo.es.WazuhSecurityEventDataCommonVo;
import com.wz.jiangsu.bean.vo.resp.PageResult;
import com.wz.jiangsu.bean.vo.resp.R;
import com.wz.jiangsu.mapper.WazuhSecurityEventDataMapper;
import com.wz.jiangsu.service.es.ESWazuhService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @program: wz
 * @author: wangzhou
 * @create: 2024-01-01 20:04
 * @description:
 **/
@Service
@Slf4j
public class ESWazuhServiceImpl implements ESWazuhService {

    @Value("${es_wazuh_inde}")
    private String wazuhIndex;

    @Autowired
    private WazuhSecurityEventDataMapper mapper;

    @Autowired
    private RestHighLevelClient client;

    @Override
    public R<WazuhSecurityEventDataCommonDtoToES> findById(String id) {
        Optional<WazuhSecurityEventDataCommonDtoToES> byId = mapper.findById(id);
//        ArrayList<String> conditions = CollUtil.newArrayList(String.valueOf(ts));
//        Iterable<WazuhSecurityEventDataCommonDtoToES> list = mapper.findAllById(conditions);
        if (byId.isPresent()) {
            WazuhSecurityEventDataCommonDtoToES wazuhSecurityEventDataCommonDtoToES = byId.get();
            return R.success(wazuhSecurityEventDataCommonDtoToES);
        }
        return R.error("没有查询到数据");
    }

    @Override
    public R<WazuhSecurityEventDataCommonDtoToES> saveOrUpdateById(WazuhSecurityEventDataCommonVo vo) {
        WazuhSecurityEventDataCommonDtoToES bean = BeanUtil.toBean(vo, WazuhSecurityEventDataCommonDtoToES.class);
        bean.setId(vo.getUuid());
        WazuhSecurityEventDataCommonDtoToES save = mapper.save(bean);
//        if (save == null) {
//            return R.error("新增或者更新失败");
//        }
        return R.success(save);
    }

    @Override
    public R<Long> count() {
        return R.success(mapper.count());
    }

    @Override
    public R<Boolean> deleteAll() {

        try {
            mapper.deleteAll();
        } catch (Exception e) {
            return R.error(Boolean.FALSE);

        }
        return R.success(Boolean.TRUE);
    }

    @Override
    public R<PageResult<List<WazuhSecurityEventDataCommonDtoToES>>> findByTs(Long ts) {
        SearchResponse response = null;
        SearchRequest request = new SearchRequest(wazuhIndex);
        // 构建查询条件
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("ts", ts));
        request.source().query(query);
        request.source().sort("eventLevel", SortOrder.ASC);

        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("异常:{}", e.getCause());
            return R.error("获取数据失败");
        }
        PageResult pageResult = getPageResult(response);
        return R.success(pageResult);

    }


    @Override
    public R<PageResult<List<WazuhSecurityEventDataCommonDtoToES>>> getResultByQueryESCondition(QueryESCondition vo) {
        SearchRequest request = new SearchRequest(wazuhIndex);
        SearchResponse response = null;
        bindRequesParams(vo, request);

        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("异常:{}", e.getCause());
            return R.error("获取数据失败");
        }
        // 获得返回结果
        PageResult pageResult = getPageResultHave(response, vo);

        return R.success(pageResult);
    }

    /**
     * 更改 requset 请求参数的值
     *
     * @param vo
     * @param request
     */
    private static void bindRequesParams(@NotNull QueryESCondition vo, SearchRequest request) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if (StrUtil.isNotBlank(vo.getAgentIp())) {
            boolQuery.must(QueryBuilders.termQuery("agentIP", vo.getAgentIp()));
        }
        if (StrUtil.isAllNotBlank(vo.getId())) {
            boolQuery.must(QueryBuilders.termQuery("id", vo.getId()));
        }

        if (StrUtil.isAllNotBlank(vo.getDataType())) {
            boolQuery.must(QueryBuilders.termQuery("dataType", vo.getDataType()));
        }

        if (StrUtil.isAllNotBlank(vo.getEventType())) {
            boolQuery.must(QueryBuilders.termQuery("eventType", vo.getEventType()));
        }

        if (StrUtil.isAllNotBlank(vo.getSeq())) {
            boolQuery.must(QueryBuilders.termQuery("seq", vo.getSeq()));
        }

        if (StrUtil.isAllNotBlank(vo.getUuid())) {
            boolQuery.must(QueryBuilders.termQuery("seq", vo.getUuid()));
        }

//        if (Objects.nonNull(vo.getTs())) {
//            boolQuery.filter(QueryBuilders.rangeQuery("ts").gte(vo.getTs()));
//        }

//        if (Objects.nonNull(vo.getEventLevel())) {
//            boolQuery.filter(QueryBuilders.rangeQuery("eventLevel").gte(vo.getEventLevel()));
//        }
//
//        if (Objects.isNull(vo.getEventLevel())) {
//            boolQuery.mustNot(QueryBuilders.existsQuery("eventLevel"));
//        }
        request.source().query(boolQuery);
        // 根据 ts（时间戳）进行倒序，根据 eventLevel 进行升序
        request.source().sort(SortBuilders.fieldSort("ts").order(SortOrder.DESC));
        request.source().sort("eventLevel", SortOrder.ASC);
        if (vo.getPageNum() >= 1 && vo.getPageSize() >= 1) {
            request.source().from((vo.getPageNum() - 1) * vo.getPageSize()).size(vo.getPageSize());
        }
    }

    /**
     * 获得返回结果
     *
     * @param response
     * @return
     */
    private static PageResult getPageResult(SearchResponse response) {
        Long totalRows = response.getHits().getTotalHits().value;
        SearchHit[] hits = response.getHits().getHits();
        List<WazuhSecurityEventDataCommonDtoToES> WazuhSecurityEventDataCommonDtoToESList = Arrays.stream(hits)
                .map(n -> JSONUtil.toBean(n.getSourceAsString(), WazuhSecurityEventDataCommonDtoToES.class))
                .collect(Collectors.toList());
        PageResult pageResult = PageResult.getPageResult(WazuhSecurityEventDataCommonDtoToESList, totalRows);

        return pageResult;
    }

    private static PageResult getPageResultHave(SearchResponse response, QueryESCondition vo) {
        Long totalRows = response.getHits().getTotalHits().value;
        SearchHit[] hits = response.getHits().getHits();
        List<WazuhSecurityEventDataCommonDtoToES> WazuhSecurityEventDataCommonDtoToESList = Arrays.stream(hits)
                .map(n -> JSONUtil.toBean(n.getSourceAsString(), WazuhSecurityEventDataCommonDtoToES.class))
                .collect(Collectors.toList());
        PageResult pageResult = PageResult.getPageResult(WazuhSecurityEventDataCommonDtoToESList, totalRows);

        pageResult.setPageNum(vo.getPageNum());
        pageResult.setPageSize(vo.getPageSize());

        pageResult.setTotalPages(PageUtil.totalPage(totalRows, vo.getPageSize()));
        Long size = totalRows % vo.getPageSize();
        // 计算当前页有多少数据
        if (pageResult.getTotalPages() >= vo.getPageNum()) {
            pageResult.setSize(Integer.valueOf(String.valueOf(size)));
        }else {
            pageResult.setSize(vo.getPageSize());
        }


        return pageResult;
    }
}
